package mn.idax.exchange.otc.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import mn.idax.exchange.otc.dto.ChatLogDto;
import mn.idax.exchange.otc.dto.OrderUserDto;
import mn.idax.exchange.otc.entity.ChatLog;
import mn.idax.exchange.otc.entity.OTCOrder;
import mn.idax.exchange.otc.entity.OTCOrderExample;
import mn.idax.exchange.otc.entity.UserInfo;
import mn.idax.exchange.otc.enums.LogTypeEnum;
import mn.idax.exchange.otc.enums.MessageNotifyTemplateEnum;
import mn.idax.exchange.otc.mapper.OTCOrderMapper;
import mn.idax.exchange.otc.mapper.UserInfoMapper;
import mn.idax.exchange.otc.repository.ChatRepository;
import mn.idax.exchange.otc.service.ChatLogService;
import mn.idax.exchange.otc.service.ChatRedisService;
import mn.idax.exchange.otc.service.FileUrlService;
import mn.idax.exchange.otc.util.I18nUtil;
import mn.idax.exchange.otc.util.ParamUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ChatLogServiceImpl implements ChatLogService {

    private static final Logger logger = LoggerFactory.getLogger(ChatLogServiceImpl.class);

    private static final String ORDER_ID = "orderId", TIME = "sendTime";

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private OTCOrderMapper otcOrderMapper;

    @Autowired
    private ChatRepository chatRepository;

    @Autowired
    private ChatRedisService chatRedisService;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private FileUrlService fileUrlService;

    @Override
    public ChatLog insert(ChatLog chatLog) {
        return chatRepository.insert(chatLog);
    }

    @Override
    public List<UserInfo> getUserInfoListByOrderId(String orderId) {
        return userInfoMapper.getUserInfoListByOrderId(orderId);
    }

    @Override
    public UserInfo getUserInfoByOrderIdAndUserId(String orderId, int userId) {
        List<UserInfo> userInfoList = this.getUserInfoListByOrderId(orderId);
        if (userInfoList != null) {
            for (UserInfo userInfo : userInfoList) {
                if (userInfo.getId().intValue() == userId) {
                    return userInfo;
                }
            }
        }
        return null;
    }

    private Map<String, JSONObject> getJsonObjectMap(List<UserInfo> userInfoList) {
        Map<String, JSONObject> resultMap = new HashMap<>();
        for (UserInfo userInfo : userInfoList) {
            resultMap.put(userInfo.getId().toString(), JSONObject.parseObject(JSON.toJSONString(userInfo)));
        }
        return resultMap;
    }

    @Override
    public List<ChatLogDto> findAllChatLog(String orderId,boolean isStaff) {
        if (StringUtils.isEmpty(orderId)) {
            return null;
        }

        Query query = new Query();
        query.addCriteria(Criteria.where(ORDER_ID).is(orderId));
        query.with(new Sort(Sort.Direction.ASC, TIME));

        List<ChatLog> chatLogs = mongoTemplate.find(query, ChatLog.class);

//        chatLogs.stream().forEach(p ->p.setSource(fileUrlService.dealFileUrlAddress(p.getSource())));
        chatLogs.stream().forEach(
                (p) ->{
                    if (!p.getLogType().equals(LogTypeEnum.staff)){
                        p.setUserLogo(fileUrlService.dealFileUrlAddress(p.getUserLogo()));
                    }
                    p.setSource(fileUrlService.dealFileUrlAddress(p.getSource()));
                }
        );

        return getChatLogDtoList(chatLogs, this.getJsonObjectMap(this.getUserInfoListByOrderId(orderId)),isStaff);
    }

    public List<ChatLogDto> getChatLogDtoList(List<ChatLog> chatLogList, Map<String, JSONObject> userMap) {

        ServletRequestAttributes requestAttrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String lang = ParamUtils.getLanguageByRequest(requestAttrs.getRequest());
        logger.info("getChatLogDtoList lang is {}",lang);

        List<ChatLogDto> resultList = new ArrayList<>();
        for (ChatLog chatLog : chatLogList) {
            ChatLogDto chatLogDto = new ChatLogDto();
            BeanUtils.copyProperties(chatLog, chatLogDto);
            if (chatLog.getLogType().equals(LogTypeEnum.system)){
                chatLogDto.setMessage(I18nUtil.getMessage(chatLog.getMessage() , lang,  chatLog.getDynamicParam()));
//                chatLogDto.setUserLogo(fileUrlService.dealFileUrlAddress(fileUrlService.dealFileUrlAddress(chatLog.getUserLogo())));
            }
            if (userMap.containsKey(chatLog.getSenderId().toString())) {
                chatLogDto.setUserName(userMap.get(chatLog.getSenderId().toString()).getString("userName"));
//                chatLogDto.setUserLogo(fileUrlService.dealFileUrlAddress(userMap.get(chatLog.getSenderId().toString()).getString("userLogo")));
            } else {
                if (LogTypeEnum.staff.equals(chatLog.getLogType())) {
                    //todo do nothing
                }
            }

//            chatLogDto.setUserLogo(fileUrlService.dealFileUrlAddress(fileUrlService.dealFileUrlAddress(chatLog.getUserLogo())));
            resultList.add(chatLogDto);
        }
        return resultList;
    }

    public List<ChatLogDto> getChatLogDtoList(List<ChatLog> chatLogList, Map<String, JSONObject> userMap, boolean isStaff) {

        List<ChatLogDto> resultList = new ArrayList<>();
        if (!isStaff){
            return getChatLogDtoList(chatLogList, userMap);
        }else {
            String lang = "zh_cn";
            for (ChatLog chatLog : chatLogList) {
                ChatLogDto chatLogDto = new ChatLogDto();
                BeanUtils.copyProperties(chatLog, chatLogDto);
                if (chatLog.getLogType().equals(LogTypeEnum.system)){
                    chatLogDto.setMessage(I18nUtil.getMessage(chatLog.getMessage() , lang,  chatLog.getDynamicParam()));
                }
                if (userMap.containsKey(chatLog.getSenderId().toString())) {
                    chatLogDto.setUserName(userMap.get(chatLog.getSenderId().toString()).getString("userName"));
//                    chatLogDto.setUserLogo(fileUrlService.dealFileUrlAddress(userMap.get(chatLog.getSenderId().toString()).getString("userLogo")));
                }

                //是系统消息&&还是客服介入
                if (chatLog.getSenderId().intValue() == 0 && chatLogDto.getMessage().equals(MessageNotifyTemplateEnum.staff_join.getContent())) {
                    continue;
                } else {
                    resultList.add(chatLogDto);
                }
            }
        }

        return resultList;
    }


    @Override
    public List<ChatLogDto> findLatestChatLog(String orderId, Integer size) {
        if (StringUtils.isEmpty(orderId)) {
            return null;
        }

        Query query = new Query();
        query.addCriteria(Criteria.where(ORDER_ID).is(orderId));
        query.limit(this.getChatLogListSize(size));
        query.with(new Sort(Sort.Direction.ASC, TIME));

        return getChatLogDtoList(mongoTemplate.find(query, ChatLog.class), this.getJsonObjectMap(this.getUserInfoListByOrderId(orderId)));
    }

    @Override
    public List<ChatLogDto> findEarlierChatLog(String orderId, Integer size, Long time) {
        if (StringUtils.isEmpty(orderId) || time == null) {
            return null;
        }

        Query query = new Query();
        query.addCriteria(Criteria.where(ORDER_ID).is(orderId).and(TIME).lt(time));
        query.limit(this.getChatLogListSize(size));
        query.with(new Sort(Sort.Direction.ASC, TIME));

        return getChatLogDtoList(mongoTemplate.find(query, ChatLog.class), this.getJsonObjectMap(this.getUserInfoListByOrderId(orderId)));
    }

    @Override
    public boolean isRelatedUser(String orderId, int userId) {
        OrderUserDto orderUserDto = this.getUserByOrderId(orderId);
        if (orderUserDto == null) {
            return false;
        }
        return orderUserDto.getBuyer().intValue() == userId || orderUserDto.getSeller().intValue() == userId;
    }

    @Override
    public OrderUserDto getUserByOrderId(String orderId) {
        OrderUserDto orderUserDto = null;
        String json = chatRedisService.getValueFromOtcOrderUser(orderId);
        if (StringUtils.isEmpty(json)) {
            OTCOrder order = getOTCOrderByOrderId(orderId);
            if (order == null) {
                return null;
            }
            orderUserDto = OrderUserDto.OrderToOrderUserDto(order);
            chatRedisService.setValueToOtcOrderUser(orderId, JSON.toJSONString(orderUserDto));
        } else {
            orderUserDto = JSON.parseObject(json, OrderUserDto.class);
        }
        return orderUserDto;
    }


    @Override
    public OTCOrder getOTCOrderByOrderId(String orderId) {
        OTCOrderExample example = new OTCOrderExample();
        example.createCriteria().andUniquekeyEqualTo(orderId);
        List<OTCOrder> otcOrderList = otcOrderMapper.selectByExample(example);
        if (otcOrderList == null || otcOrderList.isEmpty()) {
            return null;
        }
        return otcOrderList.get(0);
    }


    public OTCOrder getOTCOrderByOrderIdFix(String orderId) {
        OTCOrderExample example = new OTCOrderExample();
        example.createCriteria().andNumberEqualTo(orderId);
        List<OTCOrder> otcOrderList = otcOrderMapper.selectByExample(example);
        if (otcOrderList == null || otcOrderList.isEmpty()) {
            return null;
        }
        return otcOrderList.get(0);
    }

    private Integer getChatLogListSize(Integer size) {
        if (size == null || size.intValue() <= 0) {
            return 50;
        } else if (size.intValue() > 100) {
            return 100;
        } else {
            return size;
        }
    }

    @Override
    public UserInfo getUserInfoById(Integer id) {
        return userInfoMapper.getUserInfoById(id);
    }

    @Override
    public boolean checkIsStaffByUserId(Integer userId) {
        return userInfoMapper.checkIsStaffByUserId(userId) > 0;
    }

}
